# -*- coding: utf-8 -*-
##
## v1.50    - Rejigged all the options and Menus around.. (This has been a substantial rewrite.
##          - Fixed the Update as it wasnt currently working.
##          - Rename the config.xml into Userdata/Scripts/TorrentX.Xml
## v1.55    - Added Auto update for the remaining Modules.
## v1.56    - Small change to create the UserData/Scripts Directory if it does not exist.
## v1.57    - Fixed changing labels problem when switching between site/ctrl.

import  xbmc        ,xbmcgui
import  os          ,sys        ,traceback     ,string  ,   copy,   shutil,   zipfile  
from    types       import *
from    re          import findall      as reFindall, compile as reCompile  , sub as reSub, DOTALL as reDotAll, search as reSearch
from    urllib      import quote        as urlQuote , unquote as urlUnquote

## Constants:
VERSION         =   '1.57'                                  # version of script.
HOME_DIR        =   os.getcwd().replace(";","")+"\\"        # get homedirectory for the script
LIBS            =   HOME_DIR    +   'libs\\'                # Path to Libraries.
CTRL            =   HOME_DIR    +   'controllers\\'         # Path to configured controllers..
SITES           =   HOME_DIR    +   'sites\\'               # Path to configured sites..
LANGDIR         =   HOME_DIR    +   'language\\'            # Path to language strings

SCRIPTXML       =   'Q:\\UserData\\Scripts\\'               # Path to xbmc scripts
CFGXML          =   SCRIPTXML   +   'TorrentX.xml'          # Path to config for this script.

FILE_DIR        =   HOME_DIR    +   'files\\'               # Path to where all downloaded files go to..
GUIXML          =   'Q:\\UserData\\guisettings.xml'         # Path to xbmc guisettings.xml
SRCXML          =   'Q:\\UserData\\sources.xml'             # Path to xbmc sources.xml

sys.path.append(LIBS)                                       # Append LIBS directory to search path.
sys.path.append(CTRL)                                       # Append CTRL directory to search path.

## Make Scripts Directory if it doesnt exist.
if not os.path.exists(SCRIPTXML)    :   os.mkdir(SCRIPTXML)

## Global variable to Update core modules..
RUNSCRIPT_BOOL  =   False
RUNSCRIPT       =   HOME_DIR + 'update.py'

## Move Config File
OldCfg              =   HOME_DIR + 'config.xml'
if os.path.isfile(OldCfg)       :
    if os.path.isfile(CFGXML)   :   os.remove(OldCfg)
    else                        :   os.rename(OldCfg,CFGXML)

## Move CookieFile File
OldCkie             =   HOME_DIR + 'cookies.lwp'
NewCkie             =   'Q:\\UserData\\Scripts\\TorrentX_cookies.lwp'
if os.path.isfile(OldCkie)          :
    if os.path.isfile(CFGXML)       :   os.remove(OldCkie)
    else                            :   os.rename(OldCkie,NewCkie)

## Import Core
CORE = True
try     :   import core
except  :   CORE = False

## Setup Language
LANGOK,_        = core.Check_Lang(LANGDIR,GUIXML)

## Used by WindowXml
ResPath =   HOME_DIR + 'resources'
GUIMD   =   ResPath +'\\skins\\Default\\media'                 # Path to Images/Graphics

class GUI( xbmcgui.WindowXML ):
    def __init__( self, *args, **kwargs ):
        ## Buttons identifiers
        self.EXIT           =   [247,275,61467]
        self.A              =   [256]
        self.B              =   [257,221]
        self.X              =   [258,229]
        self.Y              =   [259,223]
        self.BLACK          =   [260,195]
        self.RIGHT          =   [273]        

        ## Static Variables
        self.ViewState      =   -1
        self.STATE_DOWN     =   1
        self.STATE_UP       =   2 
        self.STATE_SITES    =   3
        self.STATE_FILES    =   4
        self.Version        =   VERSION
        self.Dir            =   'Root'


    def onInit(self):
        try :
            ## Lock the Gui for this section ##
            xbmcgui.lock()

            #Initialize lists and read config file if it exists..
            if os.path.isfile(CFGXML)   :
                self.Config         =   core.GetAllTags('controller',CFGXML)
                self.Sites          =   core.GetAllTags('sites',CFGXML)
                self.System         =   core.GetAllTags('system',CFGXML)
            else                        :
                self.System         =   {}
                self.Config         =   {}
                self.Sites          =   {}
                
            ## Create Entry keys if they dont exist..
            if not self.System.has_key('System')                :   self.System['System']               =   {}
            if not self.System ['System'].has_key('defctrl')    :   self.System['System']['defctrl']    =   ''
            if not self.System ['System'].has_key('updates')    :   self.System['System']['updates']    =   0
            if not self.System ['System'].has_key('debug')      :   self.System['System']['debug']      =   1
            self.SysCfg         =   self.System['System']

            self.Menu           =   xbmcgui.Dialog()
            self.Progress       =   xbmcgui.DialogProgress()
            self._              =   _
            self.MEDIA          =   GUIMD +'\\'
            self.Site_          =   SITES
            self.Ctrl_          =   CTRL
            self.WebDir         =   'Q:\\web\\'     # Path to Webdir
            self.FileDir        =   FILE_DIR        # Directory for Files

            ## Code to get the State of the Webserver and create the Url for the location.
            ServerPass          =   core.ATag('webserverpassword',GUIXML,Do='File')
            ServerPort          =   core.ATag('webserverport',GUIXML,Do='File')
            ServerOn            =   core.ATag('webserver',GUIXML,Do='File')
            if ServerOn == 'true' and ServerPass ==''   :                       ## Server is correctly setup for this script.
                self.XbmcWeb    =   'http://'+ xbmc.getIPAddress() +':'+ str(ServerPort) +'/'
            else                                        :                       ## Server not setup correctly..
                self.XbmcWeb    =   None

            self.SITEID         =   ''
            self.Modules        =   {}
            self.ModFunc        =   {}
            self.SiteLabel      =   ''
            self.MyClicks       =   []
            self.Ready          =   True
            self.ButAction      =   {'A':('','',''),'B':('','',''),'X':('','',''),'Y':('','','')}
           
            self.getControl(40).setLabel('')
            self.getControl(6).setLabel(_[0])
            self.getControl(7).setLabel(_[1])
            self.getControl(8).setLabel(_[2])
            self.getControl(9).setLabel(_[3])

            self.ResetVars()
            
            ## Checks Modules or Updates and and restart if required..
            self.UpdateProcess()
            if  ( RUNSCRIPT_BOOL )  :
                self.CloseDown()
            
            if self.SysCfg['defctrl'] != ''  :
                self.SetModule('Ctrl',self.SysCfg['defctrl'],'Controller')

            ## Disable Controllist as default.
            self.getControl(50).setEnabled(False)

            ## UnLock the Gui now for normal use ##
            xbmcgui.unlock()            
        except:
            traceback.print_exc() 
            xbmcgui.unlock()            
            
    def onFocus(self,control):
        pass

##################################################################################################################
############# START ##################################### CALLING MODULES ########################################
##################################################################################################################

    def SetModule(self,Type,ModTitle,Class):
        try :
            Path = self.Modules[Type][ModTitle]['Path']
            Func = {}
            execfile(Path,Func)
            self.ModFunc[Type]  =   Func[Class](self,Path)            
        except:
            traceback.print_exc()


    def ReadModules(self,Path,Exec,Class):
        try :
            SiteName        =   []
            if Class == 'Torrents'  :   cType   =   'Site'
            else                    :   cType   =   'Ctrl'
            self.cType      =   []
            for sites in os.listdir(Path)   :
                DoPath = Path + sites +'\\'+ str(Exec)
                if os.path.isfile(DoPath)   :   SiteName.append(DoPath)
            for site in SiteName            :
                SiteData   =   {}
                execfile(site,SiteData)
                ExecAction  =   SiteData[Class](self,site)
                self.cDir.append(ExecAction.Dir)
                self.cVersion.append(ExecAction.Version)
                self.cType.append(cType)
                del SiteData                
        except :
            traceback.print_exc() 
            

    def LoadModule(self,Type,Class,xFilter=None):
        ## Types are either:    Site       or      Ctrl
        ## Class are either:    Torrents   or      Controller
        try :
            Options     =   []
            ## New section to filter for Matching Sites or Controllers.
            if      Type    ==  'Site'  :
                if self.ModFunc.has_key('Ctrl') :
                    Filter  =   self.ModFunc['Ctrl'].FileType
                    for Key in self.Modules[Type].keys()    :
                        if self.Modules[Type][Key]['FileType']  ==  Filter  :
                            Options.append(Key)
                else                            :
                    Options = self.Modules[Type].keys()
                    
            elif    xFilter !=  None  and Type == 'Ctrl':
                for Key in self.Modules[Type].keys()    :
                    if self.Modules[Type][Key]['FileType']  ==  xFilter  :
                        Options.append(Key)
            else                                        :
                Options = self.Modules[Type].keys()

            Options.sort()
            if len(Options) > 0:
                Ans = self.Menu.select(self._[21],Options)
                if Ans != -1 :
                    Func                =   {}
                    Path                =   self.Modules[Type][Options[Ans]]['Path']
                    execfile(Path,Func)
                    self.ModFunc[Type]  =   Func[Class](self,Path)
                    return True
            else            :
                return False
        except :
            traceback.print_exc() 
            return False


    def CtrlModule(self) :
        try :
            if not self.ModFunc.has_key('Ctrl') :
                Result = self.LoadModule('Ctrl','Controller')
                return Result
            else                                :
                return True
        except:
            traceback.print_exc()
            return False


    def GetModules(self):
        try :
            self.cDir       =   []
            self.cVersion   =   []
            self.cType      =   []
            self.ReadModules(SITES,'torrentsite.py','Torrents')
            self.ReadModules(CTRL ,'controller.py' ,'Controller')
        except :
            traceback.print_exc() 


##################################################################################################################
############# START ##################################### AUTO - UPDATES  ########################################
##################################################################################################################

    def UrlThread(self,url,post='',login='',isData=False,isFile='',timeout=30.0,xContent=None):
        try :
            self.xPrint('--MAIN--UrlThread ** URL:'+ str(url))
            rData           =   ''
            rOK             =   True

            self.ModFail    =   True
            while ( self.ModFail )  :
                rData,rOK       =   core.Download_URL(self,url,post,login,isData,isFile,timeout,Content=xContent)
                
            self.xPrint('--WEBDATA--: '+ str(len(rData)) +' -- '+ str(rOK))
            if not ( rOK )  :
                self.xPrint('++MAIN--UrlThread')
                return rData
            else            :
                self.xPrint('Url Data Failure')
                raise Exception
        except :
            traceback.print_exc()
            self.xPrint('==MAIN--UrlThread')
            return None


    def UpdateProcess(self,Required=False) :
        try :
            self.GetModules()
            ## Remove the New.zip file if it still exists.
            NewZip      =   HOME_DIR + 'New.zip'
            if  os.path.isfile(NewZip)      :
                os.remove(NewZip)

            ## If flag set or forced lets do it.
            if bool(int(self.SysCfg['updates'])) or Required :
                Good    =   self.DoUpdates()
                if Good     >   0   :
                    self.GetModules()
                    if  os.path.isfile(NewZip)  :
                        self.Menu.ok('Main Program','We Need to UPDATE..')
                        global RUNSCRIPT_BOOL
                        RUNSCRIPT_BOOL  =   True
        except :
            traceback.print_exc() 


    def DoUpdates(self) :
        try :
            Good    =   0
            Bad     =   0
            self.UpdateProgress(_[54],0,_[58])
            Process,List    =   self.CheckUpdate(self.cDir,self.cVersion,self.cType)
            self.UpdateProgress(_[59])                
            for i in range(len(Process)) :
                self.UpdateProgress(_[60] + str(List[i]))
                Name = str(Process[i][0])
                Vers = str(Process[i][1])
                Type = str(Process[i][2])
                Url  = str(Process[i][3])
                Old  = str(Process[i][4])
                self.xPrint(str(Name) + str(Vers))
                if      Type == 'Ctrl'  :
                    Path    =   CTRL    +   str(Name)
                    File    =   'controller.py'
                elif    Type == 'Site'  :
                    Path    =   SITES   +   str(Name)
                    File    =   'torrentsite.py'
                elif    Type == 'Main'  :
                    Path    =   HOME_DIR
                    File    =   'New.zip'
                self.UpdateProgress(_[61])

                if not os.path.isdir(Path)  :   os.mkdir(Path)
                self.UpdateProgress(_[62])

                if Type != 'Main'   :
                    Moved       =   Path +'\\'+ str(Name) +'-'+ str(Old) +'.py'
                    Original    =   Path +'\\'+ str(File)
                    if os.path.isfile(Original)    :
                        os.rename(Original,Moved)
                else                :
                    Original    =   HOME_DIR + File
                        
                self.UpdateProgress(_[63] + str(List[i]))
                URL         =   'http://xbmc-torrrent-controller.googlecode.com/files/'+ str(Process[i][3])
                WebData     =   self.UrlThread(URL,isData=True,isFile=Original)
                if  WebData == None     :
                    self.UpdateProgress(_[64] + str(List[i]))
                    Bad     = Bad + 1
                    if os.path.isfile(Original)     :   os.remove(Original)
                    if os.path.isfile(Moved)        :   os.rename(Moved,Original)
                else                    :
                    Good    = Good + 1
            self.UpdateProgress(_[31],-1)
            if Good > 0 or Bad > 0  :
                self.UpdateProgress(_[65])
                self.Menu.ok(_[66],_[67] +' ('+ str(Good) +')',_[68] +' ('+ str(Bad) +')')
                return Good
            else                    :
                return 0
        except:
            traceback.print_exc()
            self.UpdateProgress(_[31],-1)
            return Good

    def CheckUpdate(self,cDir,cVersion,cType):
        try :
            ## cDir     =   Dir      =   self.Dir
            ## cVersion =   Version  =   self.Version
            ## cType    =   Type     =   self.Type
            ## Naming convention of Files   'self.Dir-x.xx-Ctrl/Site'.py
            ## OR                           'TorrentX-x.xx-Main'.zip
            ReturnArray     =   []
            Status          =   []
            URL             =   'http://code.google.com/p/xbmc-torrrent-controller/downloads/list'
            WebData         =   self.UrlThread(URL)
            Ndata           =   []
            if  WebData != None     :
                Exp         =   reCompile('<td class=\"vt col_1\".*?'
                                          '<a.*?href=\"detail\?name=(\w+-\d\.\d\d-\w+)\.(py|zip).*?>(.*?)</a>'
                                          '.*?</td>',reDotAll)
                Data        =   reFindall( Exp,WebData )

                ## Create Array as FileName,Version
                for i in Data :
                    Furl    =   str(i[0]) +'.' + str(i[1])
                    if    str(i[1])   ==  'py'    or      \
                        ( str(i[1])   ==  'zip' and 'TorrentX' in str(i[0]) )   :
                        Tar     =   str(i[0]).split('-')
                        Ndata.append([str(Tar[0]),str(Tar[1]),str(Tar[2]),str(Furl)])
                        print 'Record : '+ str(i)

                ## Loop through the Array
                for i in Ndata  :
                    try         :   Pos     =   cDir.index(i[0]) 
                    except      :   Pos     =   -1
                    if Pos  == -1   :
                        if 'TorrentX' in i[3]   :
                            ## This is a Main Module Update.
                            if str(i[1]) > self.Version  :
                                i.append(self.Version)
                                ReturnArray.append(i)
                                Status.append(str(i[0]) + ' --Update--')                                
                        else                    :
                            ## This is a new Item   ##
                            i.append('0.00')
                            ReturnArray.append(i)
                            Status.append(str(i[0]) + ' **New**')
                    else            :
                        ## Check Version Number ##
                        if str(i[1]) > str(cVersion[Pos]) :
                            i.append(str(cVersion[Pos]))
                            ReturnArray.append(i)
                            Status.append(str(i[0]) + ' --Update--')
            else    :
                raise Exception
            return ReturnArray,Status
        except:
            traceback.print_exc()
            return [],[]


##################################################################################################################
############# START ##################################### CONFIGURATION   ########################################
##################################################################################################################

    def SetDefault(self,newdefault) :
        try :
            self.SysCfg['defctrl']  =   newdefault
        except:
            traceback.print_exc()


    def RootConfig(self):
        try :
            ## Default Setup Options
            Options     =       []

            ## Add Switch Option if a Controller Module has alreasy been Loaded..
            if self.ModFunc.has_key('Ctrl')     :   Options.append(_[49])
            
            ## Update Now and Auto update Flag settings.
            Options.append(_[54])
            if bool(int(self.SysCfg['updates'])):   Options.append(_[55] +' ['+ _[56] +']')
            else                                :   Options.append(_[55] +' ['+ _[57] +']')

            ## Toggle for Debug On/Off
            if bool(int(self.SysCfg['debug']))  :   Options.append(_[80] +' ['+ _[56] +']')
            else                                :   Options.append(_[80] +' ['+ _[57] +']')

            ## Clear Directories of Files..
            Options.append(_[89])
            Options.append(_[90])
            Options.append(_[91])
            Options.append(_[92])
            
            ## Now Process the Answer..
            Ans         =   self.Menu.select(_[50],Options)
            if Ans != -1 :
                if      Options[Ans] == _[49]     :  
                    Ans =   self.LoadModule('Ctrl','Controller')
                    self.ResetVars()
                    self.ViewState  =   -1
                elif    Options[Ans] == _[54]     :
                    self.UpdateProcess(Required=True)
                    if  ( RUNSCRIPT_BOOL )  :
                        self.CloseDown()                    
                elif    _[55] in Options[Ans]     :
                    self.SysCfg['updates']  =  self.ToggleVar(self.SysCfg['updates'])
                elif    _[80] in Options[Ans]     :
                    self.SysCfg['debug']    =  self.ToggleVar(self.SysCfg['debug'])
                elif    _[89] in Options[Ans]     :
                    self.ClearDirs('ALL')
                elif    _[90] in Options[Ans]     :
                    self.ClearDirs('torrent')
                elif    _[91] in Options[Ans]     :
                    self.ClearDirs('nzb')
                elif    _[92] in Options[Ans]     :
                    self.ClearDirs('tmp')
        except:
            traceback.print_exc()


    def ToggleVar(self,Var) :
        try :
            if bool(int(Var))   :   return 0
            else                :   return 1
        except :
            traceback.print_exc() 


    def KeyText(self,Txt,Hdr):
        try :
            keyboard = xbmc.Keyboard(str(Txt),str(Hdr))
            keyboard.doModal()
            if (keyboard.isConfirmed()):
                keystring = keyboard.getText()
                del keyboard
                return keystring
            else:
                del keyboard
                return ''
        except :
            traceback.print_exc() 
            return ''


    def ClearDirs(self,DODIR)   :
        try     :
            if DODIR == 'ALL'   :
                for EachDir in ['nzb','tmp','torrent']  :
                    self.ClearDirs(EachDir)
            else                :
                FullPath    =   str(self.FileDir) + str(DODIR) +'\\'
                for BlowFile in os.listdir(FullPath)  :
                    try :
                        os.remove(FullPath + str(BlowFile))
                    except :
                        pass
        except  :
            traceback.print_exc() 


##################################################################################################################
############# START ##################################### BASIC FUNCTIONS ########################################
##################################################################################################################

    def xPrint(self,Txt)        :
        if  ( bool(int(self.SysCfg['debug'])) )    :
            print str(Txt)


    def ResetVars(self) :
        try     :
            self.getControl(50).reset()
            self.Torrents       =   {}
            self.TorListItem    =   []
            self.GlobalMsg      =   ''
            self.Queue          =   0
            ##self.ViewState      =   -1
            self.getControl(50).setEnabled(False)
            self.getControl(20).reset()
            self.xPrint('++ResetVars')
        except:
            traceback.print_exc() 

    def Debug(self):
        try     :
            self.Menu.ok(_[22],_[23],_[24],_[25])
        except:
            traceback.print_exc() 

    def CloseDown(self) :
        try     :
            self.SaveCfg()
            self.close()
        except:
            traceback.print_exc() 


    def SaveCfg(self):
        try:
            core.PutConfig({'controller':self.Config,'sites':self.Sites,'system':self.System},CFGXML)
        except:
            traceback.print_exc() 
            self.Debug()

    def NoRecords(self) :
        try:
            self.ResetControl()
            self.Menu.ok(_[40],_[41])
        except:
            traceback.print_exc() 

        
    def UpdateProgress(self,Msg,Done=0,Heading=''):
        try :
            if  Done == -1      :
                self.Progress.close()
            else                :
                if Heading != '':
                    self.DispMsg = []
                    self.PctDone = 0
                if Done ==  0   :   self.PctDone    +=  7
                else            :   self.PctDone    =   Done
                M       = []
                Number  = 3
                self.DispMsg.append(Msg)
                if len(self.DispMsg) > 3    :   self.DispMsg.pop(0)
                else                        :   Number = len(self.DispMsg)
                if   Number == 3 :  self.Progress.update(self.PctDone,self.DispMsg[0],self.DispMsg[1],self.DispMsg[2])
                elif Number == 2 :  self.Progress.update(self.PctDone,self.DispMsg[0],self.DispMsg[1])
                elif Number == 1 :  self.Progress.create(Heading,self.DispMsg[0])
        except :
            traceback.print_exc()
            self.Progress.close()            


##################################################################################################################
############# START ##################################### LABEL FUNCTIONS ########################################
##################################################################################################################

    def ButtonLabel(self,NewButtons)   :
        try:
            ## Create new Buttons and check them..
            NewAction      =   {'A':('','',''),'B':('','',''),'X':('','',''),'Y':('','','')}
            NewAction.update(NewButtons)
            if self.ButAction !=    NewAction   :
                self.ButAction =    NewAction            
                for K,V in {'A':30,'B':32,'X':34,'Y':36}.iteritems()        :
                    if      self.ButAction[str(K)][0]   != ''   :
                        ButtonImg   =   GUIMD + '\\button-'+ str(K) +'.png'
                        ButtTxt     =   self.ButAction[str(K)][0]
                    else                                                        :
                        ButtonImg   =   GUIMD + '\\button-'+ str(K) +'-turnedoff.png'
                        ButtTxt     =   ''
                    self.getControl(int(V)).setImage(ButtonImg)
                    self.getControl(int(V)+1).setLabel(ButtTxt)
        except:
            traceback.print_exc()


    def ListLabels(self):
        try :
            Rec     =   self.getControl(50).getSelectedPosition()
            #xItem   =   self.getListItem(self.getCurrentListPosition())
            #Rec     =   self.getCurrentListPosition()
            print str(Rec)
            Lab1    =   self.TorListItem[Rec].getLabel()
            Lab2    =   self.TorListItem[Rec].getLabel2()
            return (Lab1,Lab2,Rec)
        except :
            traceback.print_exc()
            return ('','',-1)


    def ToggleLabel(self,Labels)  :
        try     :
            OktoToggle  =   True

            if      self.ViewState ==    self.STATE_UP      :
                Title       =   self.ModFunc['Ctrl'].Title
                LabArray    =   self.ModFunc['Ctrl'].UPLABEL_
                LabIndex    =   LabArray.index(self.Config[Title]['UPLABEL_'])
                
            elif    self.ViewState ==    self.STATE_DOWN    :
                Title       =   self.ModFunc['Ctrl'].Title
                LabArray    =   self.ModFunc['Ctrl'].DNLABEL_
                LabIndex    =   LabArray.index(self.Config[Title]['DNLABEL_'])
                
            elif    self.ViewState ==    self.STATE_SITES   :
                if self.TorListItem[0].getLabel2() == '**'    :
                    OktoToggle  =   False
                else                                                :
                    Title       =   self.ModFunc['Site'].Title
                    LabArray    =   self.ModFunc['Site'].LABEL_
                    LabIndex    =   LabArray.index(self.Sites[Title]['LABEL_'])

            if ( OktoToggle )   :                
                LabSize     =   len(LabArray)
                if LabSize >= 1     : ## Only action when more than one variable..
                    if      LabIndex + 1    <  LabSize      :   LabNew  =   LabIndex + 1
                    else                                    :   LabNew  =   0
                    
                    ## Change All Entries in the List
                    for i in range(0,len(self.TorListItem)) :
                        xLabel1     =   str(self.TorListItem[i].getLabel())
                        xLabel2     =   str(self.TorListItem[i].getLabel2())
                        self.TorListItem[i].setLabel2(self.Torrents[xLabel1][LabArray[LabNew]])

                    ## Change default display to the new Label
                    if      self.ViewState ==    self.STATE_UP      :
                        self.Config[Title]['UPLABEL_'] =  LabArray[LabNew] 
                    elif    self.ViewState ==    self.STATE_DOWN    :
                        self.Config[Title]['DNLABEL_'] =  LabArray[LabNew] 
                    elif    self.ViewState ==    self.STATE_SITES   :
                        self.Sites[Title]['LABEL_']    =  LabArray[LabNew] 

                    ## Update the site label with what the New Varible is
                    tsite           =   reSub('\[.*\]','',self.SiteLabel)
                    self.SiteLabel  =   tsite +'['+ str(LabArray[LabNew]) +']'
                    self.getControl(40).setLabel(self.SiteLabel)
        except :
            traceback.print_exc()


##################################################################################################################
############# START ##################################### DISPLAY PROCESS ########################################
##################################################################################################################

    def TorrentSites(self):
        try:
            Result = self.LoadModule('Site','Torrents')
            if (Result)     :
                self.ViewState  =   self.STATE_SITES
                self.ShowEntries('Site')
        except:
            traceback.print_exc()
            

    def ShowEntries(self,xType='Ctrl',xData=('','',''),xSearch=None):
        try:
            self.xPrint('--ShowEntries')
            self.UpdateProgress(_[26],0,_[27])
            Nothing =   False
            Data    =   None
            
            ## Variables Being returned in the Data Dictionary:
            ## Torrents,TorListItem,Queue,GlobalMsg
            if      xType == 'Ctrl' :
                Data    =   self.ModFunc[xType].GetDownloads()
            elif    xType == 'Site' :
                Data    =   self.ModFunc[xType].GetDownloads(xData,xSearch)
            
            self.UpdateProgress(_[28])

            if Data == None     :
                ## A Failure occurred so Display Error message.
                self.Debug()
            else                :
                ## No Failure so update the Lists with the new data.
                if Data.has_key('TorListItem')              :
                    if  len(Data['TorListItem'])    >   0   :
                        ## We have new Data in the list so replace everything..
                        self.ResetVars()
                        self.Torrents       =   Data['Torrents']
                        self.TorListItem    =   Data['TorListItem']
                        if Data.has_key('Queue')        :   self.Queue          =   Data['Queue']
                        else                            :   self.Queue          =   0
                        if Data.has_key('GlobalMsg')    :   self.GlobalMsg      =   Data['GlobalMsg']
                        else                            :   self.GlobalMsg      =   ''
                        for Entry in self.TorListItem   :
                            self.getControl(50).addItem(Entry)                    
                        self.getControl(20).addLabel(self.GlobalMsg)

                        ## We have Data then enable the Control.
                        self.getControl(50).setEnabled(True)
                    else                                                :   Nothing = True
                else                                                    :   Nothing = True

            if ( Nothing )  :
                ## No Data was received so Inform the User and leave the old List if not uploads or downloads.
                if      self.ViewState  ==  self.STATE_UP   or  \
                        self.ViewState  ==  self.STATE_DOWN     :       self.ResetVars()                   
                self.Menu.ok(_[69],_[78],_[79])

            ## There was was previous data anyway so Disable controllist and move focus back to top.
            if  len(self.TorListItem) == 0  :
                self.getControl(50).setEnabled(False)
                if      self.ViewState   ==   self.STATE_DOWN   :   self.setFocus(self.getControl(6))   
                elif    self.ViewState   ==   self.STATE_UP     :   self.setFocus(self.getControl(7))   
                elif    self.ViewState   ==   self.STATE_FILES  :   self.setFocus(self.getControl(6))
                elif    self.ViewState   ==   self.STATE_SITES  :   self.setFocus(self.getControl(8))
            else                            :
                self.getControl(40).setLabel(self.SiteLabel)
                self.getControl(50).setEnabled(True)
                self.setFocus(self.getControl(50))
                control     =   self.getFocusId()
                self.PostControl(control)

            ## Close Dialog
            self.UpdateProgress(_[31],-1)
            
            self.xPrint('++ShowEntries')
        except:
            traceback.print_exc()
            self.UpdateProgress(_[31],-1)
            self.xPrint('==ShowEntries')


##################################################################################################################
############# START ##################################### CONTROL CODE    ########################################
##################################################################################################################

    def onClick( self, control ):
        self.xPrint('--onClick')
        if ( self.Ready )       :               ##  Only do this if theres nothing running..
            self.Ready      =   False

            if      control == 6            :
                if ( self.CtrlModule() )    :
                    self.ModFunc['Ctrl'].FILEHASH   =   ''
                    self.ModFunc['Ctrl'].TORRENT    =   ''
                    self.ViewState = self.STATE_DOWN
                    self.ShowEntries('Ctrl')
                    ##self.getControl(40).setLabel(self.SiteLabel)

            elif    control == 7            :
                if ( self.CtrlModule() )    :
                    self.ModFunc['Ctrl'].FILEHASH   =   ''
                    self.ModFunc['Ctrl'].TORRENT    =   ''
                    self.ViewState = self.STATE_UP
                    self.ShowEntries('Ctrl')
                    ##self.getControl(40).setLabel(self.SiteLabel)

            elif    control == 8            :
                if ( self.LoadModule('Site','Torrents') )           :
                    self.ViewState = self.STATE_SITES
                    self.Do_Keys(('Select/Action','','rootmenu'),('','',-1))
                    ##self.getControl(40).setLabel(self.SiteLabel)

            elif    control == 9            :
                self.RootConfig()

            elif    control == 50           :
                self.Do_Keys(self.ButAction['A'],self.ListLabels())
                                    
            else                                                        :   pass
            ##self.PostControl(control)
            self.Ready      =   True
        else        :
            pass
        self.xPrint('++onControl')


    def onAction(self,action):
        self.xPrint('--onAction')
        ButtonCode  =   action.getButtonCode()
        control     =   self.getFocusId()
        
        if ( self.Ready ) :  ## Only run this when we are in a ready state...
            self.Ready = False
        
            ### Exit ###
            if      ( ButtonCode in self.EXIT ) :
                self.CloseDown()

            ### B KEY ###
            elif    ( ButtonCode in self.B )    :
                self.Do_Keys(self.ButAction['B'],self.ListLabels())

            ### X KEY ###
            elif    ( ButtonCode in self.X )    :
                self.Do_Keys(self.ButAction['X'],self.ListLabels())

            ### Y KEY ###
            elif    ( ButtonCode in self.Y )    :
                self.Do_Keys(self.ButAction['Y'],self.ListLabels())

            ### BLACK KEY ###
            elif    ( ButtonCode in self.BLACK ):
                if control == 50    :
                    if      self.ViewState == self.STATE_SITES          :
                        SearchText = self.KeyText('',_[53])
                        if SearchText != ''                             :
                            self.Do_Keys(('','',''),('','',-1),xSearch=str(SearchText))
                            
                    elif    self.ViewState == self.STATE_DOWN or self.ViewState == self.STATE_UP    :
                        self.AddFileMenu()
                        
                elif    ( control in [6,7] ) and ( self.ViewState in [1,2] )    :
                    self.AddFileMenu()                    

            ### TOGGLE LABEL ###
            elif    ( ButtonCode in self.RIGHT ) and ( control == 50 )  and     \
                    ( self.ViewState in [1,2,3] )                               :
                self.ToggleLabel(self.ListLabels())
                        
            ## Dont Do Anything
            else                                                        :
                pass
           
            self.PostControl(self.getFocusId())
            self.Ready = True            
        else            :
            pass
        self.xPrint('++onAction')
            

    def PostControl(self,control)   :
        try     :
            self.xPrint('--PostControl :'+ str(control))
            ## Only do if something has been selected already..
            if      self.ViewState in [1,2,3,4]                     :

                ## Reset labels and buttons.
                self.getControl(20).reset()

                ## Setup  Site/Ctrl string and Setup Message accordingly.
                if      self.ViewState  ==  self.STATE_SITES        :
                    xType   =   'Site'
                else                                                :
                    xType   =   'Ctrl'
                    self.getControl(20).addLabel(self.GlobalMsg)
                    
                ## Check that the Control has a key.
                if  not self.ModFunc[xType].KeyMenus.has_key(str(self.ViewState) + str(control))  :
                    doControl   =   '0'
                else                                                        :
                    doControl   =   str(self.ViewState) + str(control)

                ## Now grab the Keys to display them and do it..
                self.ButtonLabel(self.ModFunc[xType].KeyMenus[doControl])
                
        except :
            traceback.print_exc()                
            self.xPrint('==PostControl')


    def Do_Keys(self,Buttons,Labels,xSearch=None)  :
        try     :
            self.xPrint('--Do_Keys')
            if      Buttons[2]   !=  '' :   ## Action
                if  self.ViewState in [1,2,4]   :
                    ## Check the returned Variables.
                    ## Worked   =   success or failure of the KeyAction process.
                    ## Refresh  =   A refresh of the list is required.
                    Worked,Refresh  =   self.ModFunc['Ctrl'].KeyAction(Buttons,Labels)
                    if not ( Worked )   :
                        self.Debug()
                    else                :
                        if ( Refresh )  :
                            self.ShowEntries()

                elif    self.ViewState == self.STATE_SITES      :
                    Worked,Refresh,Data =   self.ModFunc['Site'].KeyAction(Buttons,Labels,xSearch)
                    if not ( Worked )   :
                        self.Debug()
                    else                :
                        if ( Refresh )  :
                            self.ShowEntries(xType='Site',xData=Data)

                else                                            :   return
            else                                                                :
                self.xPrint('Nothing defined in Action.....')
            self.xPrint('++Do_Keys')
        except :
            traceback.print_exc()                
            self.xPrint('==Do_Keys')


##################################################################################################################
############# START ##################################### ADDING TORRENT CODE ####################################
##################################################################################################################

    def MultiPart(self,fields,files,ftype) :
        try     :
            self.xPrint('--MultiPart')
            Boundary   =   '----------ThIs_Is_tHe_bouNdaRY_---$---'
            CrLf       =   '\r\n'
            L          =   []

            ## Process the Fields required..
            for (key, value) in fields              :
                L.append('--' + Boundary)
                L.append('Content-Disposition: form-data; name="%s"' % key)
                L.append('')
                L.append(value)

            ## Process the Files..
            for (key, filename, value) in files     :
                L.append('--' + Boundary)
                L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))

                ## Set filetype based on .torrent or .nzb files.
                if ftype == 'torrent'       :   filetype = 'application/x-bittorrent'
                else                        :   filetype = 'text/xml'
                L.append('Content-Type: %s' % filetype)

                ## Now add the actual Files Data
                L.append('')
                L.append(value)

            ## Add End of data..
            L.append('--' + Boundary + '--')
            L.append('')

            ## Heres the Main stuff that we will be passing back..
            post            = CrLf.join(L)
            content_type    = 'multipart/form-data; boundary=%s' % Boundary

            ## Return the formatted data..
            self.xPrint('++MultiPart')
            return content_type, post
        except  :
            traceback.print_exc()
            self.xPrint('==MultiPart')
            return None,None


    def AddFileMenu(self)       :
        try     :
            self.xPrint('--AddFileMenu')
            ## Check if a Ctrl Module has been Loaded..
            if ( self.CtrlModule() ) :
                ## Module present so check for files and Types to Add.
                xType       =   self.ModFunc['Ctrl'].FileType
                LookDir     =   str(FILE_DIR) + str(xType) +'\\'
                Options     =   []
                Options.append('-- Send All Files --')
                for fset in os.listdir(LookDir) :
                    Options.append(str(fset))

                ## Display Menu..
                Ans         =   self.Menu.select(_[77],Options)
                if Ans != -1 :
                    if      Ans  ==  0      :
                        ## Do All Has Been Requested..
                        Options.pop(0)
                        Add_Array   =   Options
                    
                    elif    Ans  >=  1      :
                        ## Perform Single Request
                        Add_Array   =   [Options[Ans]]

                    ## Loop Through the Items in The list and Process them and Update the Display.
                    self.UpdateProgress(_[36],0,_[36])
                    count   =   0
                    good    =   0
                    for Each in Add_Array   :
                        good    +=      1
                        if  ( self.ModFunc['Ctrl'].SendTorrent(LookDir,Each) )  :
                            self.xPrint(str(Each) + ' - Worked..')
                            count   +=      1
                        else                                                    :
                            self.xPrint(str(Each) + ' - Failed..')
                        self.UpdateProgress(str(Each))
                    self.UpdateProgress(_[31],-1)

                    ## If any errors occurred display a message..
                    if good != count    :
                        Ok  =   self.Menu.ok(_[81],_[82])

                    ## Now Load the Downloads list..
                    self.ModFunc['Ctrl'].FILEHASH   =   ''
                    self.ModFunc['Ctrl'].TORRENT    =   ''
                    self.ViewState = self.STATE_DOWN
                    self.ShowEntries('Ctrl')
                    ##self.getControl(40).setLabel(self.SiteLabel)
            
            self.xPrint('++AddFileMenu')
        except  :
            traceback.print_exc()
            self.xPrint('==AddFileMenu')
            self.UpdateProgress(_[31],-1)
            return False

##################################################################################################################
############# START ################################ FILE HANDLING ###############################################
##################################################################################################################

    def SaveFiles(self,fType,fName,fData)  :
        try     :
            self.xPrint('--SaveFiles')
            ## Create static directory locations.
            TmpDir  =   FILE_DIR    +   'tmp\\'
            ToDir   =   FILE_DIR    +   fType   +'\\'
            TmpFile =   TmpDir + 'myfile.zip'

            ## Remove temporary file if it exists.
            if os.path.isfile(TmpFile)  :   os.remove(TmpFile)
            
            ## Check the Type of file from the Data if so extract the file.
            if reSearch('PK\003\004',fData) !=  None            :

                ## Save into a temporary file..
                try     :
                    TmpFile =   TmpDir + 'myfile.zip'
                    f       =   open(TmpFile,'wb')
                    f.write(fData)
                    f.close()
                except  :
                    traceback.print_exc()
                    if 'f' in locals()          :   f.close()
                    if os.path.isfile(TmpFile)  :
                        os.remove(TmpFile)
                    return None
                
                tZip    =   zipfile.ZipFile(TmpFile,'r')
                for fset in tZip.namelist() :
                    if fset.endswith(fType)     :
                        fData       =   tZip.read(fset)
                tZip.close()
                os.remove(TmpFile)                

            ## Now make a nice filename..
            NewName     =   self.NiceName(fName,fType)
            print 'Name:'+ str(ToDir) + str(NewName)
            if NewName  ==  None    :   raise Exception

            ## Save The file
            try     :
                f   =   open(str(ToDir) + str(NewName),'wb')
                f.write(fData)
                f.close()
            except  :
                traceback.print_exc()
                if 'f' in locals()              :   f.close()
                if os.path.isfile(str(NewName)) :
                    os.remove(str(NewName))
                return None               

            self.xPrint('++SaveFiles')
            return (ToDir,NewName)
        except  :
            traceback.print_exc()
            self.xPrint('==SaveFiles')
            return None
                        

    def NiceName(self,fName,fType)  :
        try     :
            NewName     =   ''
            tName       =   fName.rsplit('.',1)
            xName       =   tName[0][:30]
            if ( xName[0].isdigit() )   :
                xName = 'x'+ str(xName)
            for xChar in xName                  :
                if      xChar.isalnum()         :   NewName  += str(xChar)
                elif    xChar.isspace()         :   NewName  += '_'
                else                            :   pass
            if len(NewName) > 4                 :
                return NewName +'.'+ fType
            else                                :
                return None
        except  :
            traceback.print_exc()
            return None


##################################################################################################################
############# START ##################################### CALLER #################################################
##################################################################################################################

if ( LANGOK ) and ( CORE )  :
    if ( __name__ == "__main__" ) :
        MyDisplay = GUI( "skin.xml", ResPath , "Default" )
        MyDisplay.doModal()
        del MyDisplay
    else                                                :
        xbmcgui.Dialog().ok("GUI ERROR","Problem loading skin.")        
else                        :
    xbmcgui.Dialog().ok("ERROR","Problem with Language/Core.")

## If Runscript then Action it
if  ( RUNSCRIPT_BOOL )  :
    xbmc.executescript(RUNSCRIPT)    
